#pragma once

#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <unistd.h>
#include "Thread.hpp"
#include "LockGuard.hpp"

namespace ThreadNS
{
    static const int defaultnum = 5;

    // 线程数据
    class ThreadData
    {
    public:
        ThreadData(const std::string &name) : threadname(name)
        {
        }
        ~ThreadData()
        {
        }

    public:
        std::string threadname;
    };

    template <class T>
    class ThreadPool
    {
    private:
        ThreadPool(int num = defaultnum) : _thread_num(num)
        {
            pthread_mutex_init(&_mutex, nullptr);
            pthread_cond_init(&_cond, nullptr);
            // 创建指定个数的线程
            for (int i = 0; i < _thread_num; i++)
            {
                std::string threadname = "thread-";
                threadname += std::to_string(i + 1);

                ThreadData td(threadname);
                // 创建
                // Thread<ThreadData> t(threadname, std::bind(&ThreadPool<T>::ThreadRun, this, std::placeholders::_1), td);
                // _threads.push_back(t);
                // 两种写法都可行，这种写法可以减少拷贝
                _threads.emplace_back(threadname, std::bind(&ThreadPool<T>::ThreadRun, this, std::placeholders::_1), td);
            }
        }
        ThreadPool(const ThreadPool<T> &tp) = delete;
        const ThreadPool<T> &operator=(const ThreadPool<T>) = delete;

    public:
        static ThreadPool<T> *GetInstance() // 创建单例
        {
            if (instance == nullptr)
            {
                LockGuard lockguard(&sig_lock); // 在多线程中存在线程安全问题，需要注意加锁
                if (instance == nullptr)
                {
                    instance = new ThreadPool<T>();
                }
            }

            return instance;
        }
        // 启动线程池
        bool Start()
        {
            for (auto &thread : _threads)
            {
                thread.Start();
            }
            return true;
        }
        void ThreadWait() // 等待
        {
            pthread_cond_wait(&_cond, &_mutex);
        }
        void ThreadWakeup() // 唤醒
        {
            pthread_cond_signal(&_cond);
        }
        // 执行任务
        void ThreadRun(ThreadData &td)
        {
            while (true)
            {
                T t;
                // 取任务
                {
                    // 加锁
                    LockGuard lockguard(&_mutex);
                    while (_q.empty())
                    {
                        // 没有任务时就等待
                        ThreadWait();
                    }
                    t = _q.front();
                    _q.pop();
                }
                // 处理任务
                t();
            }
        }
        // 添加任务
        void Push(const T &in)
        {
            // 加锁
            LockGuard lockguard(&_mutex);
            // 添加
            _q.push(in);
            // 唤醒
            ThreadWakeup();
        }
        // 等待线程
        void Wait()
        {
            for (auto &thread : _threads)
            {
                thread.Join();
            }
        }
        ~ThreadPool()
        {
            pthread_mutex_destroy(&_mutex);
            pthread_cond_destroy(&_cond);
        }

    private:
        std::queue<T> _q;                         // 任务队列
        std::vector<Thread<ThreadData>> _threads; // 线程池
        int _thread_num;                          // 线程个数
        pthread_mutex_t _mutex;                   // 锁
        pthread_cond_t _cond;                     // 条件变量

        static ThreadPool<T> *instance;
        static pthread_mutex_t sig_lock;
    };

    template <class T>
    ThreadPool<T> *ThreadPool<T>::instance = nullptr;
    template <class T>
    pthread_mutex_t ThreadPool<T>::sig_lock = PTHREAD_MUTEX_INITIALIZER;
}
